from django.shortcuts import render
from django.urls import reverse, reverse_lazy
from django.http import HttpResponse
from django.views.generic import ListView, CreateView, DeleteView, UpdateView
from django.utils import timezone
from django.db.models import Q
from django.http import HttpResponseRedirect
from .forms import AppForm
from .models import App
from public.user_group import is_admin_group, is_right


# Create your views here.
class AppInputCreateView(CreateView):
    # 该模板路径为“appinput/templates/appinput/”下
    template_name = 'appinput/create_appinput.html'
    model = App
    # 表示我们在创建APp应用的全段网页表单时，将会使用AppForm里的字段来渲染。
    form_class = AppForm

    # 该方法用来进行权限控制
    def get(self, request, *args, **kwargs):
        # 定义用户权限，判断用户是否时管理员中的一个成员（is_admin_group），则可以创建App
        if is_admin_group(self.request.user):
            # 这里一定要返回，否则不能正常处理请求。只会返回else内容
            return super().get(request, *args, **kwargs)
        else:
            result = "亲， 没有权限， 只有管理员才能进入！"
            return HttpResponse(result)

    # 该方法，当用户通过前端网页表单提供的数据不合法时，会返回创建App的页面，而不会进行数据库插入操作
    # 不合法包括但不限于：必填字段未填写，在数字字段输入字符，输入长度超出限制等等
    def form_invalid(self, form):
        print(form)
        return self.render_to_response({'form': form})

    # 如果用户提交的表单通过合法性验证，将执行此方法。其调用了Django的ORM的create方法，该方法直接进行数据库保存，不需要save()方法
    def form_valid(self, form):
        App.objects.create(
            name=form.cleaned_data['name'],
            description=form.cleaned_data['description'],
            jenkins_job=form.cleaned_data['jenkins_job'],
            git_url=form.cleaned_data['git_url'],
            build_cmd=form.cleaned_data['build_cmd'],
            package_name=form.cleaned_data['package_name'],
            zip_package_name=form.cleaned_data['zip_package_name'],
            is_restart_status=form.cleaned_data['is_restart_status'],
            script_url=form.cleaned_data['script_url'],
            manage_user=form.cleaned_data['manage_user'],
        )
        # HttpResponseRedirect重定向跳转
        # reverse("appinput:list")反向解析URL，将url路径appinput:list，解析出路径（/appinput/list/）
        return HttpResponseRedirect(reverse("appinput:list"))

    # 为视图增加额外的上下文的方法
    def get_context_data(self, **kwargs):
        # 首先要继承该上下文
        context = super().get_context_data(**kwargs)
        # 新增上下文参数，可以用{{now}},{{current_page}},{{current_page_name}}在前端html中获取该值
        context['now'] = timezone.now()
        context['current_page'] = "appinput-create"
        context['current_page_name'] = "新增App应用"
        return context


class AppInputListView(ListView):
    template_name = 'appinput/list_appinput.html'
    # 指明每页显示10个App服务
    paginate_by = 10

    def get_queryset(self):
        if self.request.GET.get('search_pk'):
            search_pk = self.request.GET.get('search_pk')
            return App.objects.filter(
                # 是一个or或的连接"|"，其查询的字段分别是name和package_name字段
                # __icontains是模糊查询前端获得的值search_pk.
                Q(name__icontains=search_pk) |
                Q(package_name__icontains=search_pk)
            )
        return App.objects.all()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now()
        context['is_admin_group'] = is_admin_group(self.request.user)
        context['current_page'] = "appinput-list"
        context['current_page_name'] = "App应用列表"
        # 实现前端正确的分页，其完成为“http://127.0.0.1:8000/app/list/?search_pk=Z&page=2”
        query_string = self.request.META.get('QUERY_STRING')
        if 'page' in query_string:
            # 此时的query_list为['http://127.0.0.1:8000/app/list/?search_pk=Z', 'page=2']
            query_list = query_string.split('&')
            # 此时的query_list为['http://127.0.0.1:8000/app/list/?search_pk=Z']
            query_list = [elem for elem in query_list if not elem.startswith('page')]
            # 此时的query_string为?http://127.0.0.1:8000/app/list/?search_pk=Z&
            # '?' + "&".join(query_list)将列表query_list内的所有元素用&连连接成一个字符串，因为其中只有一个元素，所以就编程了：
            # ?http://127.0.0.1:8000/app/list/?search_pk=Z，所以后面还要加一个&
            query_string = '?' + "&".join(query_list) + '&'
        # 不是空，就是说明没有分页是全部显示。即没有page参数
        elif query_string is not None:
            # 此时的query_string为?http://127.0.0.1:8000/app/list/?search_pk=Z&
            query_string = '?' + query_string + '&'
        context['current_url'] = query_string
        return context


class AppInputDetailView(DeleteView):
    template_name = 'appinput/detail_appinput.html'
    model = App

    # DeleteView会根据出入的pk_url_kwarg来直接搜索出相应的数据。
    # get_object：用于查询单条数据；get_queryset：用来获得数据列表。两者调用一个另一个就不会调用
    # 因为在显示列表时，由于URL中不携带参数，所以调用get_queryset；在编辑和显示详情及删除时，在URL中带有pk参数，所以调用get_object方法
    # 在get_object方法中：queryset = queryset.filter(pk=pk)；obj = queryset.get()
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['current_page_name'] = "App应用详情"
        context['now'] = timezone.now()
        return context


class AppInputUpdateView(UpdateView):
    template_name = 'appinput/edit_appinput.html'
    model = App
    form_class = AppForm

    def get(self, request, *args, **kwargs):
        # 定义用户权限
        app_id = request.path.split("/")[-2]
        app_item = App.objects.get(id=app_id)
        if is_admin_group(self.request.user) or app_item.manage_user == self.request.user:
            return super().get(request, *args, **kwargs)
        else:
            result = "亲， 没有权限， 只有管理员才可以进入！"
            return HttpResponse(result)

    '''
    # 在提交时，限制非法用户权限
    def post(self, request, *args, **kwargs):
        app_id = request.path.split("/")[-2]
        app_item = App.objects.get(id=app_id)
        if is_admin_group(self.request.user) or app_item.manage_user == self.request.user:
            return super().post(request, *args, **kwargs)
        else:
            result = "亲，没有权限，想用非正规方式修改吧？"
            return HttpResponse(result)
    '''

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['current_page'] = "appinput-edit"
        context['current_page_name'] = "编辑App应用"
        context['app_id'] = self.kwargs.get(self.pk_url_kwarg)
        return context

    def get_success_url(self):
        return reverse_lazy("appinput:list")
